Skip to content

一、概述

Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。

  • 应用
    1. http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。
    2. 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
    3. 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

1.1 常用命令

sh
# 启动命令


<NolebasePageProperties />




./nginx

# 关闭
./nginx -s stop
./nginx -s quit

# 刷新加载配置文件
./nginx -s reload

-?和-h:显示帮助信息

-v:打印版本号信息并退出

-V:打印版本号信息和配置信息并退出

-t:测试nginx的配置文件语法是否正确并退出

-T:测试nginx的配置文件语法是否正确并列出用到的配置文件信息然后退出

-q:在配置测试期间禁止显示非错误消息

-s:signal信号,后面可以跟

	 stop[快速关闭,类似于TERM/INT信号的作用]

	quit[优雅的关闭,类似于QUIT信号的作用] 

	reopen[重新打开日志文件类似于USR1信号的作用] 

	reload[类似于HUP信号的作用]

-p:prefix,指定Nginx的prefix路径,(默认为: /usr/local/nginx/)

-c:filename,指定Nginx的配置文件路径,(默认为: conf/nginx.conf)

-g:用来补充Nginx配置文件,向Nginx服务指定启动时应用全局的配置

1.2 信号控制

Nginx后台进程中包含一个master进程和多个worker进程,master进程主要用来管理worker进程,包含接收外界的信息,并将接收到的信号发送给各个worker进程,监控worker进程的状态,当worker进程出现异常退出后,会自动重新启动新的worker进程。而worker进程则是专门用来处理用户请求的,各个worker进程之间是平等的并且相互独立,处理请求的机会也是一样的。

获取nginx线程的id可通过ps -ef | grep nginx或nginx配置参数的--pid-path=PATH指定的配置文件(默认是/usr/local/nginx/logs/nginx.pid)。

信号

信号作用
TERM/INT立即关闭整个服务
QUIT"优雅"地关闭整个服务(work进程不再接收新的请求,等所有请求处理完后,在把进程都关闭掉)
HUP重读配置文件并使用服务对新配置项生效(优雅关闭后重启)
USR1重新打开日志文件,可以用来进行日志切割
USR2平滑升级到最新版的nginx
WINCH所有子进程不在接收处理新连接,相当于给work进程发送QUIT指令(master进程不会关闭)

调用命令为kill -signal PID

signal:即为信号;PID即为获取到的master线程ID

1.3 目录跳转问题

在0.8.48之前,nginx的server_name_in_redirect配置为on,该配置在请求地址是,会自动做一个301的重定向,会定向为http://server_name/目录名/为off是为http://原URL中的域名/目录名/该问题会导致一些请求存在问题。可以通过rewrite解决rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;

1.4 目录合并

搜索引擎优化(SEO)是一种利用搜索引擎的搜索规则来提供目的网站的有关搜索引擎内排名的方式。我们在创建自己的站点时,可以通过很多中方式来有效的提供搜索引擎优化的程度。其中有一项就包含URL的目录层级一般不要超过三层,否则的话不利于搜索引擎的搜索也给客户端的输入带来了负担,但是将所有的文件放在一个目录下又会导致文件资源管理混乱并且访问文件的速度也会随着文件增多而慢下来,可通过rewrite解决上述问题。利用可配置正则表达式的特性。

server {
	listen 80;
	server_name www.web.name;
	location /server{
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /server/$1/$2/$3/$4/$5.html last;
	}
}

二、配置文件

Nginx的核心配置文件默认是放在/usr/local/nginx/conf/nginx.conf,默认有三大块:全局块、events块、http块。

http块中可以配置多个server块,每个server块又可以配置多个location块。

2.1 配置内容示例

conf
#全局块,主要设置Nginx服务器整体运行的配置指令
##全局块 begin##
#配置允许运行Nginx工作进程的用户和用户组
user www;
#配置运行Nginx进程生成的worker进程数
worker_processes 2;
#配置Nginx服务器运行对错误日志存放的路径
error_log logs/error.log;
#配置Nginx服务器允许时记录Nginx的master进程的PID文件路径和名称
pid logs/nginx.pid;
#配置Nginx服务是否以守护进程方法启动
#daemon on;
##全局块 end##

#events块,主要设置,Nginx服务器与用户的网络连接,这一部分对Nginx服务器的性能影响较大
##events块 begin##
events{
	#设置Nginx网络连接序列化
	accept_mutex on;
	#设置Nginx的worker进程是否可以同时接收多个请求
	multi_accept on;
	#设置Nginx的worker进程最大的连接数
	worker_connections 1024;
	#设置Nginx使用的事件驱动模型
	use epoll;
}
##events块 end##

#http块,是Nginx服务器配置中的重要部分,代理、缓存、日志记录、第三方模块配置...
##http块 start##
http{
	#定义MIME-Type
	include mime.types;
	default_type application/octet-stream;
	#配置允许使用sendfile方式运输
	sendfile on;
	#配置连接超时时间
	keepalive_timeout 65;
	#配置请求处理日志格式
	log_format server1 '===>server1 access log';
	log_format server2 '===>server2 access log';
	##server块 开始##
	include /home/www/conf.d/*.conf;
	##server块 结束##
}
##http块 end##

server{
		#配置监听端口和主机名称
		listen 8081;
		server_name localhost;
		#配置请求处理日志存放路径
		access_log /home/www/myweb/server1/logs/access.log server1;
		#配置错误页面
		error_page 404 /404.html;
		#配置处理/server1/location1请求的location
		location /server1/location1{
			root /home/www/myweb;
			index index_sr1_location1.html;
		}
		#配置处理/server1/location2请求的location
		location /server1/location2{
			root /home/www/myweb;
			index index_sr1_location2.html;
		}
		#配置错误页面转向
		location = /404.html {
			root /home/www/myweb;
			index 404.html;
		}
}

2.2 全局块

user

用于配置运行Nginx服务器的worker进程的用户和用户组。

语法user user [group]
默认值nobody
位置全局块

该属性也可以在编译的时候指定,语法如下./configure --user=user --group=group,如果两个地方都进行了设置,最终生效的是配置文件中的配置。

sh
user www;

# 需要添加用户
useradd www
work process指令

master_process:用来指定是否开启工作进程。

语法master_process on|off;
默认值master_process on;
位置全局块

worker_processes:用于配置Nginx生成工作进程的数量,这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。

语法worker_processes num/auto;
默认值1
位置全局块
daemon

设定Nginx是否以守护进程的方式启动。

守护式进程是linux后台执行的一种服务进程,特点是独立于控制终端,不会随着终端关闭而停止。

语法daemon on|off;
默认值daemon on;
位置全局块
pid

用来配置Nginx当前master进程的进程号ID存储的文件路径。

语法pid file;
默认值默认为:/usr/local/nginx/logs/nginx.pid
位置全局块

该属性可以通过./configure --pid-path=PATH来指定

error_log

用来配置Nginx的错误日志存放路径

语法error_log file [日志级别];
默认值error_log logs/error.log error;
位置全局块、http、server、location

该属性可以通过./configure --error-log-path=PATH来指定

其中日志级别的值有:debug|info|notice|warn|error|crit|alert|emerg,翻译过来为试|信息|通知|警告|错误|临界|警报|紧急,这块建议大家设置的时候不要设置成info以下的等级,因为会带来大量的磁盘I/O消耗,影响Nginx的性能。

include

用来引入其他配置文件,使Nginx的配置更加灵活

语法include file;
默认值
位置any

2.3 events块

accept_mutex

用来设置Nginx网络连接序列化

语法accept_mutex on|off;
默认值accept_mutex on;
位置events

这个配置主要可以用来解决常说的"惊群"问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响Nginx的整体性能。如果将上述值设置为on(开启状态),将会对多个Nginx进程接收连接进行序列号,一个个来唤醒接收,就防止了多个进程对连接的争抢。

multi_accept

用来设置是否允许同时接收多个网络连接

语法multi_accept on|off;
默认值multi_accept off;
位置events

如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接

worker_connections

用来配置单个worker进程最大的连接数

语法worker_connections number;
默认值worker_commections 512;
位置events

这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数。另外,number值不能大于操作系统支持打开的最大文件句柄数量。

use

用来设置Nginx服务器选择哪种事件驱动来处理网络消息。

语法use method;
默认值根据操作系统定
位置events

注意:此处所选择事件处理模型是Nginx优化部分的一个重要内容,method的可选值有select/poll/epoll/kqueue等,之前在准备centos环境的时候,我们强调过要使用linux内核在2.6以上,就是为了能使用epoll函数来优化Nginx。

另外这些值的选择,我们也可以在编译的时候使用

--with-select_module--without-select_module

--with-poll_module --without-poll_module来设置是否需要将对应的事件驱动模块编译到Nginx的内核。

配置示例
events{
	accept_mutex on;
	multi_accept on;
	worker_commections 1024;
	use epoll;
}

2.4 http块

定义MIME-Type,响应类型

浏览器中可以显示的内容有HTML、XML、GIF等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIME Type。所以说MIME Type是网络资源的媒体类型。

在Nginx的配置文件中,默认有两行配置

include mime.types;
default_type application/octet-stream;
default_type

用来配置Nginx响应前端请求默认的MIME类型。可设置xml、html、json多种格式。

语法default_type mime-type;
默认值default_type text/plain;
位置http、server、location

include mime.types把mime.types文件中MIMT类型与相关类型文件的文件后缀名的对应关系加入到当前的配置文件中。

自定义服务日志

Nginx中日志的类型分access.log、error.log。

access.log:用来记录用户所有的访问请求。

error.log:记录nginx本身运行时的错误信息,不会记录用户的访问请求。

Nginx服务器支持对服务日志的格式、大小、输出等进行设置,需要使用到两个指令,分别是access_log和log_format指令。

access_log

用来设置用户访问日志的相关属性。

语法access_log path[format[buffer=size]]
默认值access_log logs/access.log combined;
位置http, server, location
log_format

用来指定日志的输出格式。

语法log_format name [escape=default|json|none] string....;
默认值log_format combined "...";
位置http
sendfile

用来设置Nginx服务器是否使用sendfile()传输文件,该属性可以大大提高Nginx处理静态资源的性能

语法sendfile on|off;
默认值sendfile off;
位置http、server、location
keepalive_timeout

用来设置长连接的超时时间。

》为什么要使用keepalive?

我们都知道HTTP是一种无状态协议,客户端向服务端发送一个TCP请求,服务端响应完毕后断开连接。
如何客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较多,使用keepalive模式,可以告诉服务器端在处理完一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。
语法keepalive_timeout time;
默认值keepalive_timeout 75s;
位置http、server、location
keepalive_requests

用来设置一个keep-alive连接使用的次数。

语法keepalive_requests number;
默认值keepalive_requests 100;
位置http、server、location

2.5 Server配置

listen指令

listen:用来配置监听端口。

语法listen address[:port] [default_server]...;
listen port [default_server]...;
默认值listen *:80 | *:8000
位置server

listen的设置比较灵活,常用的设置方式:

listen 127.0.0.1:8000; // listen localhost:8000 监听指定的IP和端口
listen 127.0.0.1;	监听指定IP的所有端口
listen 8000;	监听指定端口上的连接
listen *:8000;	监听指定端口上的连接

default_server属性是标识符,用来将此虚拟主机设置成默认主机。所谓的默认主机指的是如果没有匹配到对应的address:port,则会默认执行的。如果不指定默认使用的是第一个server。

server_name指令

server_name:用来设置虚拟主机服务名称。

127.0.0.1 、 localhost 、域名[www.baidu.com | www.jd.com]

语法server_name name ...;
name可以提供多个中间用空格分隔
默认值server_name "";
位置server

关于server_name的配置方式有三种:

精确匹配
server {
	listen 80;
	server_name www.itcast.cn www.itheima.cn;
	...
}

可通过修改请求机器的hosts文件,windows:C:\Windows\System32\drivers\etc centos:/etc/hosts

使用通配符配置

server_name中支持通配符"*",但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段,如:

server {
	listen 80;
	server_name  *.itcast.cn	www.itheima.*;
	# www.itcast.cn abc.itcast.cn www.itheima.cn www.itheima.com
	...
}
使用正则表达式配置

server_name中可以使用正则表达式,并且使用~作为正则表达式字符串的开始标记。

常见的正则表达式

代码说明
^匹配搜索字符串开始位置
$匹配搜索字符串结束位置
.匹配除换行符\n之外的任何单个字符
\转义字符,将下一个字符标记为特殊字符
[xyz]字符集,与任意一个指定字符匹配
[a-z]字符范围,匹配指定范围内的任何字符
\w与以下任意字符匹配 A-Z a-z 0-9 和下划线,等效于[A-Za-z0-9_]
\d数字字符匹配,等效于[0-9]
{n}正好匹配n次
{n,}至少匹配n次
{n,m}匹配至少n次至多m次
*零次或多次,等效于{0,}
+一次或多次,等效于{1,}
?零次或一次,等效于{0,1}

配置如下:

server{
        listen 80;
        server_name ~^www\.(\w+)\.com$;
        default_type text/plain;
        return 200 $1  $2 ..;
}
注意 ~后面不能加空格,括号可以取值
匹配执行顺序
No1:准确匹配server_name

No2:通配符在开始时匹配server_name成功

No3:通配符在结束时匹配server_name成功

No4:正则表达式匹配server_name成功

No5:被默认的default_server处理,如果没有指定默认找第一个server

location块

uri映射

location:用来设置请求的URI

语法location [ = | ~ | ~* | ^~ |@ ] uri
默认值
位置server,location

uri变量是待匹配的请求字符串,可以不包含正则表达式,也可以包含正则表达式,那么nginx服务器在搜索匹配location的时候,是先使用不包含正则表达式进行匹配,找到一个匹配度最高的一个,然后在通过包含正则表达式的进行匹配,如果能匹配到直接访问,匹配不到,就使用刚才匹配度最高的那个location来处理请求。

属性介绍:

不带符号,要求必须以指定模式开始

server {
	listen 80;
	server_name 127.0.0.1;
	location /abc{
		default_type text/plain;
		return 200 "access success";
	}
}
以下访问都是正确的
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
http://192.168.200.133/abc/
http://192.168.200.133/abcdef

= : 用于不包含正则表达式的uri前,必须与指定的模式精确匹配

server {
	listen 80;
	server_name 127.0.0.1;
	location =/abc{
		default_type text/plain;
		return 200 "access success";
	}
}
可以匹配到
http://192.168.200.133/abc
http://192.168.200.133/abc?p1=TOM
匹配不到
http://192.168.200.133/abc/
http://192.168.200.133/abcdef

~ : 用于表示当前uri中包含了正则表达式,并且区分大小写 ~*: 用于表示当前uri中包含了正则表达式,并且不区分大小写

换句话说,如果uri包含了正则表达式,需要用上述两个符合来标识

server {
	listen 80;
	server_name 127.0.0.1;
	location ~^/abc\w${
		default_type text/plain;
		return 200 "access success";
	}
}
server {
	listen 80;
	server_name 127.0.0.1;
	location ~*^/abc\w${
		default_type text/plain;
		return 200 "access success";
	}
}

^~: 用于不包含正则表达式的uri前,功能和不加符号的一致,唯一不同的是,如果模式匹配,那么就停止搜索其他模式了。

server {
	listen 80;
	server_name 127.0.0.1;
	location ^~/abc{
		default_type text/plain;
		return 200 "access success";
	}
}
访问控制
sh
# allow 指定了允许访问的IP或网络段
#语法:allow [ address | CIDR | all ] 默认值:no
#使用字段:http, server, location, limit_except

# deny 指定了拒绝访问的IP或网络段
# 语法:deny [ address | CIDR | all ] 默认值:no
# 使用字段:http, server, location, limit_except
# HttpAccess模块可以和error_page指令搭配使用来重定向一个未经验证的访问请求。
error_page  403  http://example.com/forbidden.html;
location / {
  deny192.168.1.1;
  allow   192.168.1.0/24;
  allow   10.1.1.0/16;
  denyall;
}

设置请求目录的资源root / alias

root:设置请求的根目录

语法root path;
默认值root html;
位置http、server、location

path为Nginx服务器接收到请求以后查找资源的根目录路径。

alias:用来更改location的URI

语法alias path;
默认值
位置location

path为修改后的根路径。

root配置路径处理后为:root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的含义。
如果location路径是以/结尾,则alias也必须是以/结尾,root没有要求

index指令

设置网站的默认首页

语法index file ...;
默认值index index.html;
位置http、server、location

index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,则会依次进行查找,找到第一个为止。

error_page指令

设置网站的错误页面

语法error_page code ... [=[response]] uri;
默认值
位置http、server、location......

当出现对应的响应code后,如何来处理。

(1)可以指定具体跳转的地址

server {
	error_page 404 http://www.itcast.cn;
}

(2)可以指定重定向地址

server{
	error_page 404 /50x.html;
	error_page 500 502 503 504 /50x.html;
	location =/50x.html{
		root html;
	}
}

(3)使用location的@符合完成错误信息展示

server{
	error_page 404 @jump_to_error;
	location @jump_to_error {
		default_type text/plain;
		return 404 'Not Found Page...';
	}
}

可选项=[response]的作用是用来将相应代码更改为另外一个

server{
	error_page 404 =200 /50x.html;
	location =/50x.html{
		root html;
	}
}
这样的话,当返回404找不到对应的资源的时候,在浏览器上可以看到,最终返回的状态码是200,这块需要注意下,编写error_page后面的内容,404后面需要加空格,200前面不能加空格

三、核心功能

3.1 Rewrite功能

Rewrite是Nginx服务器提供的一个重要基本功能,是Web服务器产品中几乎必备的功能。主要的作用是用来实现URL的重写。

注意:Nginx服务器的Rewrite功能的实现依赖于PCRE的支持,因此在编译安装Nginx服务器之前,需要安装PCRE库。Nginx使用的是ngx_http_rewrite_module模块来解析和处理Rewrite功能的相关配置。

"地址重写"与"地址转发"

重写和转发的区别:

地址重写浏览器地址会发生变化而地址转发则不变
一次地址重写会产生两次请求而一次地址转发只会产生一次请求
地址重写到的页面必须是一个完整的路径而地址转发则不需要
地址重写因为是两次请求所以request范围内属性不能传递给新页面而地址转发因为是一次请求所以可以传递值
地址转发速度快于地址重写

set指令

该指令用来设置一个新的变量。

语法set $variable value;
默认值
位置server、location、if

variable:变量的名称,该变量名称要用"$"作为变量的第一个字符,且不能与Nginx服务器预设的全局变量同名。

value:变量的值,可以是字符串、其他变量或者变量的组合等。

Rewrite常用全局变量

变量说明
$args变量中存放了请求URL中的请求指令。比如http://192.168.200.133:8080?arg1=value1&args2=value2中的"arg1=value1&arg2=value2",功能和$query_string一样
$http_user_agent变量存储的是用户访问服务的代理信息(如果通过浏览器访问,记录的是浏览器的相关版本信息)
$host变量存储的是访问服务器的server_name值
$document_uri变量存储的是当前访问地址的URI。比如http://192.168.200.133/server?id=10&name=zhangsan中的"/server",功能和$uri一样
$document_root变量存储的是当前请求对应location的root值,如果未设置,默认指向Nginx自带html目录所在位置
$content_length变量存储的是请求头中的Content-Length的值
$content_type变量存储的是请求头中的Content-Type的值
$http_cookie变量存储的是客户端的cookie信息,可以通过add_header Set-Cookie 'cookieName=cookieValue'来添加cookie数据
$limit_rate变量中存储的是Nginx服务器对网络连接速率的限制,也就是Nginx配置中对limit_rate指令设置的值,默认是0,不限制。
$remote_addr变量中存储的是客户端的IP地址
$remote_port变量中存储了客户端与服务端建立连接的端口号
$remote_user变量中存储了客户端的用户名,需要有认证模块才能获取
$scheme变量中存储了访问协议
$server_addr变量中存储了服务端的地址
$server_name变量中存储了客户端请求到达的服务器的名称
$server_port变量中存储了客户端请求到达服务器的端口号
$server_protocol变量中存储了客户端请求协议的版本,比如"HTTP/1.1"
$request_body_file变量中存储了发给后端服务器的本地文件资源的名称
$request_method变量中存储了客户端的请求方式,比如"GET","POST"等
$request_filename变量中存储了当前请求的资源文件的路径名
$request_uri变量中存储了当前请求的URI,并且携带请求参数,比如http://192.168.200.133/server?id=10&name=zhangsan中的"/server?id=10&name=zhangsan"

if指令

该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置。

语法if (condition)
默认值
位置server、location

condition为判定条件,可以支持以下写法:

  1. 变量名。如果变量名对应的值为空或者是0,if都判断为false,其他条件为true。
if ($param){
	
}
2. 使用"="和"!="比较变量和字符串是否相等,满足条件为true,不满足为false
if ($request_method = POST){
	return 405;
}

注意:此处和Java不太一样的地方是字符串不需要添加引号。

  1. 使用正则表达式对变量进行匹配,匹配成功返回true,否则返回false。变量与正则表达式之间使用"~","~*","!~","!~*"来连接。

    "~"代表匹配正则表达式过程中区分大小写,

    "~*"代表匹配正则表达式过程中不区分大小写

    "!~"和"!~*"刚好和上面取相反值,如果匹配上返回false,匹配不上返回true

if ($http_user_agent ~ MSIE){
	#$http_user_agent的值中是否包含MSIE字符串,如果包含返回true
}

注意:正则表达式字符串一般不需要加引号,但是如果字符串中包含"}"或者是";"等字符时,就需要把引号加上。

  1. 判断请求的文件是否存在使用"-f"和"!-f",

    当使用"-f"时,如果请求的文件存在返回true,不存在返回false。

    当使用"!f"时,如果请求文件不存在,但该文件所在目录存在返回true,文件和目录都不存在返回false,如果文件存在返回false

if (-f $request_filename){
	#判断请求的文件是否存在
}
if (!-f $request_filename){
	#判断请求的文件是否不存在
}
  1. 判断请求的目录是否存在使用"-d"和"!-d",

    当使用"-d"时,如果请求的目录存在,if返回true,如果目录不存在则返回false

    当使用"!-d"时,如果请求的目录不存在但该目录的上级目录存在则返回true,该目录和它上级目录都不存在则返回false,如果请求目录存在也返回false.

  2. 判断请求的目录或者文件是否存在使用"-e"和"!-e"

    当使用"-e",如果请求的目录或者文件存在时,if返回true,否则返回false.

    当使用"!-e",如果请求的文件和文件所在路径上的目录都不存在返回true,否则返回false

  3. 判断请求的文件是否可执行使用"-x"和"!-x"

    当使用"-x",如果请求的文件可执行,if返回true,否则返回false

    当使用"!-x",如果请求文件不可执行,返回true,否则返回false

break指令

该指令用于中断当前相同作用域中的其他Nginx配置。与该指令处于同一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效。

语法break;
默认值
位置server、location、if

例子:

location /{
	if ($param){
		set $id $1;
		break;
		limit_rate 10k;
	}
}

return指令

该指令用于完成对请求的处理,直接向客户端返回响应状态代码。在return后的所有Nginx配置都是无效的。

语法return code [text];
return code URL;
return URL;
默认值
位置server、location、if

code:为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理

text:为返回给客户端的响应体内容,支持变量的使用

URL:为返回给客户端的URL地址

rewrite指令

该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。

URL和URI的区别:

URI:统一资源标识符
URL:统一资源定位符
语法rewrite regex replacement [flag];
默认值
位置server、location、if

regex:用来匹配URI的正则表达式

replacement:匹配成功后,用于替换URI中被截取内容的字符串。如果该字符串是以"http://"或者"https://"开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端。

flag:用来设置rewrite对URI的处理行为,可选值有如下:

  • last:终止继续在本location块中处理接收到的URI,并将此处重写的URI作为一个新的URI,使用各location块进行处理。该标志将重写后的URI重写在server块中执行,为重写后的URI提供了转入到其他location块的机会。
  • break:将此处重写的URI作为一个新的URI,在本块中继续进行处理。该标志将重写后的地址在当前的location块中执行,不会将新的URI转向其他的location块。
  • redirect:将重写后的URI返回给客户端,状态码为302,指明是临时重定向URI,主要用在replacement变量不是以"http://"或者"https://"开头的情况。请求会被临时重定向,浏览器地址也会发生改变
  • permanent:将重写后的URI返回给客户端,状态码为301,指明是永久重定向URI,主要用在replacement变量不是以"http://"或者"https://"开头的情况。请求会被永久重定向,浏览器地址也会发生改变

域名跳转过程中携带参数,可通过 正则表达式匹配值,通过$1替换

rewrite_log指令

该指令配置是否开启URL重写日志的输出功能。

语法rewrite_log on|off;
默认值rewrite_log off;
位置http、server、location、if

开启后,URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件汇总。

3.2 反向代理

Nginx即可以实现正向代理,也可以实现反向代理。

proxy_pass

该指令用来设置被代理服务器地址,可以是主机名称、IP地址加端口号形式。

语法proxy_pass URL;
默认值
位置location

URL:为要设置的被代理服务器地址,包含传输协议(http,https://)、主机名称或IP地址加端口号、URI等要素。

举例:

proxy_pass http://www.baidu.com;
location /server{}
proxy_pass http://192.168.200.146;
    http://192.168.200.146/server/index.html
proxy_pass http://192.168.200.146/;
    http://192.168.200.146/index.html

反向代理后缀加不加/问题

不加/ 会将location地址拼接上,加就不会拼接。

server{
	listen 80;
	server_name localhost;
	location /server{
		#proxy_pass http://192.168.200.146;
		proxy_pass http://192.168.200.146/;
	}
}
当客户端访问 http://localhost/server/index.html
这个时候,第一个proxy_pass就变成了http://localhost/server/index.html
第二个proxy_pass就变成了http://localhost/index.html

proxy_set_header

该指令可以更改Nginx服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给代理的服务器。代理服务器可获取请求头信息

语法proxy_set_header field value;
默认值proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
位置http、server、location

proxy_redirect

该指令是用来重置头信息中的"Location"和"Refresh"的值。

语法proxy_redirect redirect replacement;
proxy_redirect default;
proxy_redirect off;
默认值proxy_redirect default;
位置http、server、location

proxy_redirect redirect replacement;

redirect:目标,Location的值
replacement:要替换的值

proxy_redirect default;

default;
将location块的uri变量作为replacement,
将proxy_pass变量作为redirect进行替换

proxy_redirect off;

关闭proxy_redirect的功能

3.3 负载均衡

概述

系统的扩展可以分为纵向扩展和横向扩展。

纵向扩展是从单机的角度出发,通过增加系统的硬件处理能力来提升服务器的处理能力

横向扩展是通过添加机器来满足大型网站服务的处理能力。

应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。

负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。

负载均衡作用

1、解决服务器的高并发压力,提高应用程序的处理性能。

2、提供故障转移,实现高可用。

3、通过添加或减少服务器数量,增强网站的可扩展性。

4、在负载均衡器上进行过滤,可以提高系统的安全性。

负载均衡实现

方式一:用户手动选择

这种方式比较原始,只要实现的方式就是在网站主页上面提供不同线路、不同服务器链接方式,让用户来选择自己访问的具体服务器,来实现负载均衡。

方式二:DNS轮询方式

DNS

域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换。

大多域名注册商都支持对同一个主机名添加多条A记录,这就是DNS轮询,DNS服务器将解析请求按照A记录的顺序,随机分配到不同的IP上,这样就能完成简单的负载均衡。DNS轮询的成本非常低,在一些不重要的服务器,被经常使用。

验证:

ping www.nginx521.cn

清空本地的dns缓存

ipconfig/flushdns

我们发现使用DNS来实现轮询,不需要投入过多的成本,虽然DNS轮询成本低廉,但是DNS负载均衡存在明显的缺点。

1.可靠性低

假设一个域名DNS轮询多台服务器,如果其中的一台服务器发生故障,那么所有的访问该服务器的请求将不会有所回应,即使你将该服务器的IP从DNS中去掉,但是由于各大宽带接入商将众多的DNS存放在缓存中,以节省访问时间,导致DNS不会实时更新。所以DNS轮流上一定程度上解决了负载均衡问题,但是却存在可靠性不高的缺点。

2.负载均衡不均衡

DNS负载均衡采用的是简单的轮询负载算法,不能区分服务器的差异,不能反映服务器的当前运行状态,不能做到为性能好的服务器多分配请求,另外本地计算机也会缓存已经解析的域名到IP地址的映射,这也会导致使用该DNS服务器的用户在一定时间内访问的是同一台Web服务器,从而引发Web服务器减的负载不均衡。

负载不均衡则会导致某几台服务器负荷很低,而另外几台服务器负荷确很高,处理请求的速度慢,配置高的服务器分配到的请求少,而配置低的服务器分配到的请求多。

方式三:四/七层负载均衡

介绍四/七层负载均衡之前,我们先了解一个概念,OSI(open system interconnection),叫开放式系统互联模型,这个是由国际标准化组织ISO指定的一个不基于具体机型、操作系统或公司的网络体系结构。该模型将网络通信的工作分为七层。

应用层:为应用程序提供网络服务。

表示层:对数据进行格式化、编码、加密、压缩等操作。

会话层:建立、维护、管理会话连接。

传输层:建立、维护、管理端到端的连接,常见的有TCP/UDP。

网络层:IP寻址和路由选择

数据链路层:控制网络层与物理层之间的通信。

物理层:比特流传输。

所谓四层负载均衡指的是OSI七层模型中的传输层,主要是基于IP+PORT的负载均衡

实现四层负载均衡的方式:
硬件:F5 BIG-IP、Radware等
软件:LVS、Nginx、Hayproxy等

所谓的七层负载均衡指的是在应用层,主要是基于虚拟的URL或主机IP的负载均衡

实现七层负载均衡的方式:
软件:Nginx、Hayproxy等

四层和七层负载均衡的区别

四层负载均衡数据包是在底层就进行了分发,而七层负载均衡数据包则在最顶端进行分发,所以四层负载均衡的效率比七层负载均衡的要高。
四层负载均衡不识别域名,而七层负载均衡识别域名。

处理四层和七层负载以为其实还有二层、三层负载均衡,二层是在数据链路层基于mac地址来实现负载均衡,三层是在网络层一般采用虚拟IP地址的方式实现负载均衡。

实际环境采用的模式

四层负载(LVS)+七层负载(Nginx)

3.4 Nginx七层负载均衡

Nginx要实现七层负载均衡需要用到proxy_pass代理模块配置。Nginx默认安装支持这个模块,我们不需要再做任何处理。Nginx的负载均衡是在Nginx的反向代理基础上把用户的请求根据指定的算法分发到一组【upstream虚拟服务池】。

Nginx七层负载均衡的指令

upstream指令

该指令是用来定义一组服务器,它们可以是监听不同端口的服务器,并且也可以是同时监听TCP和Unix socket的服务器。服务器可以指定不同的权重,默认为1。

语法upstream name
默认值
位置http
server指令

该指令用来指定后端服务器的名称和一些参数,可以使用域名、IP、端口或者unix socket

语法server name [paramerters]
默认值
位置upstream

负载均衡状态

代理服务器在负责均衡调度中的状态有以下几个:

状态概述
down当前的server暂时不参与负载均衡
backup预留的备份服务器
max_fails允许请求失败的次数
fail_timeout经过max_fails失败后, 服务暂停时间
max_conns限制最大的接收连接数
down

down:将该服务器标记为永久不可用,那么该代理服务器将不参与负载均衡。

upstream backend{
	server 192.168.200.146:9001 down;
	server 192.168.200.146:9002
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}

该状态一般会对需要停机维护的服务器进行设置。

backup

backup:将该服务器标记为备份服务器,当主服务器不可用时,将用来传递请求。

upstream backend{
	server 192.168.200.146:9001 down;
	server 192.168.200.146:9002 backup;
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}

此时需要将9094端口的访问禁止掉来模拟下唯一能对外提供访问的服务宕机以后,backup的备份服务器就要开始对外提供服务,此时为了测试验证,我们需要使用防火墙来进行拦截。

介绍一个工具firewall-cmd,该工具是Linux提供的专门用来操作firewall的。

查询防火墙中指定的端口是否开放

firewall-cmd --query-port=9001/tcp

如何开放一个指定的端口

firewall-cmd --permanent --add-port=9002/tcp

批量添加开发端口

firewall-cmd --permanent --add-port=9001-9003/tcp

如何移除一个指定的端口

firewall-cmd --permanent --remove-port=9003/tcp

重新加载

firewall-cmd --reload

其中

​ --permanent表示设置为持久

​ --add-port表示添加指定端口

​ --remove-port表示移除指定端口

max_conns

max_conns=number:用来设置代理服务器同时活动链接的最大数量,默认为0,表示不限制,使用该配置可以根据后端服务器处理请求的并发量来进行设置,防止后端服务器被压垮。

max_fails和fail_timeout

max_fails=number:设置允许请求代理服务器失败的次数,默认为1。

fail_timeout=time:设置经过max_fails失败后,服务暂停的时间,默认是10秒。

upstream backend{
	server 192.168.200.133:9001 down;
	server 192.168.200.133:9002 backup;
	server 192.168.200.133:9003 max_fails=3 fail_timeout=15;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}

负载均衡策略

介绍完Nginx负载均衡的相关指令后,我们已经能实现将用户的请求分发到不同的服务器上,那么除了采用默认的分配方式以外,我们还能采用什么样的负载算法?

Nginx的upstream支持如下六种方式的分配算法,分别是:

算法名称说明
轮询默认方式
weight权重方式
ip_hash依据ip分配方式
least_conn依据最少连接方式
url_hash依据URL分配方式
fair依据响应时间方式
轮询

是upstream模块负载均衡默认的策略。每个请求会按时间顺序逐个分配到不同的后端服务器。轮询不需要额外的配置。

upstream backend{
	server 192.168.200.146:9001 weight=1;
	server 192.168.200.146:9002;
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}
weight加权[加权轮询]

weight=number:用来设置服务器的权重,默认为1,权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,所有此策略比较适合服务器的硬件配置差别比较大的情况。

upstream backend{
	server 192.168.200.146:9001 weight=10;
	server 192.168.200.146:9002 weight=5;
	server 192.168.200.146:9003 weight=3;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}
ip_hash

当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某一个IP的用户在后端Web服务器A上登录后,在访问该站点的其他URL,能保证其访问的还是后端web服务器A。

语法ip_hash;
默认值
位置upstream
upstream backend{
	ip_hash;
	server 192.168.200.146:9001;
	server 192.168.200.146:9002;
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}

需要额外多说一点的是使用ip_hash指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,有些后端服务器接收的请求少,而且设置后端服务器权重等方法将不起作用。

least_conn

最少连接,把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

upstream backend{
	least_conn;
	server 192.168.200.146:9001;
	server 192.168.200.146:9002;
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}

此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。

url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。

upstream backend{
	hash &request_uri;
	server 192.168.200.146:9001;
	server 192.168.200.146:9002;
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}
fair

fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能的进行负载均衡。那么如何使用第三方模块的fair负载均衡策略。

upstream backend{
	fair;
	server 192.168.200.146:9001;
	server 192.168.200.146:9002;
	server 192.168.200.146:9003;
}
server {
	listen 8083;
	server_name localhost;
	location /{
		proxy_pass http://backend;
	}
}

但是如何直接使用会报错,因为fair属于第三方模块实现的负载均衡。需要添加nginx-upstream-fair,如何添加对应的模块:

  1. 下载nginx-upstream-fair模块
下载地址为:
	https://github.com/gnosek/nginx-upstream-fair
  1. 将下载的文件上传到服务器并进行解压缩
unzip nginx-upstream-fair-master.zip
  1. 重命名资源
mv nginx-upstream-fair-master fair
  1. 使用./configure命令将资源添加到Nginx模块中
./configure --add-module=/root/fair
  1. 编译
make

编译可能会出现如下错误,ngx_http_upstream_srv_conf_t结构中缺少default_port

解决方案:

在Nginx的源码中 src/http/ngx_http_upstream.h,找到ngx_http_upstream_srv_conf_s,在模块中添加添加default_port属性

in_port_t	   default_port

然后再进行make.

  1. 更新Nginx

​ 6.1 将sbin目录下的nginx进行备份

mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginxold

​ 6.2 将安装目录下的objs中的nginx拷贝到sbin目录

cd objs
cp nginx /usr/local/nginx/sbin

​ 6.3 更新Nginx

cd ../
make upgrade
  1. 编译测试使用Nginx

3.5 Nginx四层负载均衡

Nginx在1.9之后,增加了一个stream模块,用来实现四层协议的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听,然后通过proxy_pass来转发我们的请求,通过upstream添加多个后端服务,实现负载均衡。

四层协议负载均衡的实现,一般都会用到LVS、HAProxy、F5等,要么很贵要么配置很麻烦,而Nginx的配置相对来说更简单,更能快速完成工作。

添加stream模块的支持

Nginx默认是没有编译这个模块的,需要使用到stream模块,那么需要在编译的时候加上--with-stream

完成添加--with-stream的实现步骤:

》将原有/usr/local/nginx/sbin/nginx进行备份
》拷贝nginx之前的配置信息
》在nginx的安装源码进行配置指定对应模块  ./configure --with-stream
》通过make模板进行编译
》将objs下面的nginx移动到/usr/local/nginx/sbin下
》在源码目录下执行  make upgrade进行升级,这个可以实现不停机添加新模块的功能

Nginx四层负载均衡的指令

stream指令

该指令提供在其中指定流服务器指令的配置文件上下文。和http指令同级。

语法stream
默认值
位置main
upstream指令

该指令和http的upstream指令是类似的。

3.6 Nginx缓存集成

缓存就是数据交换的缓冲区(称作:Cache),当用户要获取数据的时候,会先从缓存中去查询获取数据,如果缓存中有就会直接返回给用户,如果缓存中没有,则会发请求从服务器重新查询数据,将数据返回给用户的同时将数据放入缓存,下次用户就会直接从缓存中获取数据。

缓存的优点

​ 1.减少数据传输,节省网络流量,加快响应速度,提升用户体验;

​ 2.减轻服务器压力;

​ 3.提供服务端的高可用性;

缓存的缺点

​ 1.数据的不一致

​ 2.增加成本

Nginx的web缓存服务

Nginx是从0.7.48版开始提供缓存功能。Nginx是基于Proxy Store来实现的,其原理是把URL及相关组合当做Key,在使用MD5算法对Key进行哈希,得到硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录中。它可以支持任意URL连接,同时也支持404/301/302这样的非200状态码。Nginx即可以支持对指定URL或者状态码设置过期时间,也可以使用purge命令来手动清除指定URL的缓存。

Nginx缓存设置的相关指令

Nginx的web缓存服务主要是使用ngx_http_proxy_module模块相关指令集来完成.

proxy_cache_path

该指定用于设置缓存文件的存放路径

语法proxy_cache_path path [levels=number]
keys_zone=zone_name:zone_size [inactive=time][max_size=size];
默认值
位置http

path:缓存路径地址,如:

/usr/local/proxy_cache

levels: 指定该缓存空间对应的目录,最多可以设置3层,每层取值为1|2如 :

levels=1:2   缓存空间有两层目录,第一次是1个字母,第二次是2个字母
举例说明:
itheima[key]通过MD5加密以后的值为 43c8233266edce38c2c9af0694e2107d
levels=1:2   最终的存储路径为/usr/local/proxy_cache/d/07
levels=2:1:2 最终的存储路径为/usr/local/proxy_cache/7d/0/21
levels=2:2:2 最终的存储路径为??/usr/local/proxy_cache/7d/10/e2

keys_zone:用来为这个缓存区设置名称和指定大小,如:

keys_zone=itcast:200m  缓存区的名称是itcast,大小为200M,1M大概能存储8000个keys

inactive:指定缓存的数据多次时间未被访问就将被删除,如:

inactive=1d   缓存数据在1天内没有被访问就会被删除

max_size:设置最大缓存空间,如果缓存空间存满,默认会覆盖缓存时间最长的资源,如:

max_size=20g

配置实例:

http{
	proxy_cache_path /usr/local/proxy_cache keys_zone=itcast:200m  levels=1:2:1 inactive=1d max_size=20g;
}
proxy_cache

该指令用来开启或关闭代理缓存,如果是开启则自定使用哪个缓存区来进行缓存。

语法proxy_cache zone_name|off;
默认值proxy_cache off;
位置http、server、location

zone_name:指定使用缓存区的名称

proxy_cache_key

该指令用来设置web缓存的key值,Nginx会根据key值MD5哈希存缓存。

语法proxy_cache_key key;
默认值proxy_cache_key $scheme$proxy_host$request_uri;
位置http、server、location
proxy_cache_valid

该指令用来对不同返回状态码的URL设置不同的缓存时间

语法proxy_cache_valid [code ...] time;
默认值
位置http、server、location

如:

proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
为200和302的响应URL设置10分钟缓存,为404的响应URL设置1分钟缓存
proxy_cache_valid any 1m;
对所有响应状态码的URL都设置1分钟缓存
proxy_cache_min_uses

该指令用来设置资源被访问多少次后被缓存

语法proxy_cache_min_uses number;
默认值proxy_cache_min_uses 1;
位置http、server、location
proxy_cache_methods

该指令用户设置缓存哪些HTTP方法

语法proxy_cache_methods GET|HEAD|POST;
默认值proxy_cache_methods GET HEAD;
位置http、server、location

默认缓存HTTP的GET和HEAD方法,不缓存POST方法。

Nginx缓存的清除

方式一:删除对应的缓存目录
rm -rf /usr/local/proxy_cache/......
方式二:使用第三方扩展模块
ngx_cache_purge

(1)下载ngx_cache_purge模块对应的资源包,并上传到服务器上。

ngx_cache_purge-2.3.tar.gz

(2)对资源文件进行解压缩

tar -zxf ngx_cache_purge-2.3.tar.gz

(3)修改文件夹名称,方便后期配置

mv ngx_cache_purge-2.3 purge

(4)查询Nginx的配置参数

nginx -V

(5)进入Nginx的安装目录,使用./configure进行参数配置

./configure --add-module=/root/nginx/module/purge

(6)使用make进行编译

make

(7)将nginx安装目录的nginx二级制可执行文件备份

mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginxold

(8)将编译后的objs中的nginx拷贝到nginx的sbin目录下

cp objs/nginx /usr/local/nginx/sbin

(9)使用make进行升级

make upgrade

(10)在nginx配置文件中进行如下配置

server{
	location ~/purge(/.*) {
		proxy_cache_purge itcast itheima;
	}
}

Nginx设置资源不缓存

proxy_no_cache

该指令是用来定义不将数据进行缓存的条件。

语法proxy_no_cache string ...;
默认值
位置http、server、location

配置实例

proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass

该指令是用来设置不从缓存中获取数据的条件。

语法proxy_cache_bypass string ...;
默认值
位置http、server、location

配置实例

proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;

上述两个指令都有一个指定的条件,这个条件可以是多个,并且多个条件中至少有一个不为空且不等于"0",则条件满足成立。上面给的配置实例是从官方网站获取的,里面使用到了三个变量,分别是$cookie_nocache、$arg_nocache、$arg_comment

这三个参数分别代表的含义是:

$cookie_nocache
指的是当前请求的cookie中键的名称为nocache对应的值
$arg_nocache和$arg_comment
指的是当前请求的参数中属性名为nocache和comment对应的属性值

案例演示下:

log_format params $cookie_nocache | $arg_nocache | $arg_comment;
server{
	listen	8081;
	server_name localhost;
	location /{
		access_log logs/access_params.log params;
		add_header Set-Cookie 'nocache=999';
		root html;
		index index.html;
	}
}

四、拓展

4.1 nginx平滑升级

使用Nginx服务信号进行升级

sh
#将原始版本的sbin目录下的nginx进行备份
cd /usr/local/nginx/sbin
mv nginx nginxold
# 将编译后objs目录下的nginx文件,拷贝到`/usr/local/nginx/sbin`目录下
cp nginx /usr/local/nginx/sbin
# 发送信号USR2给Nginx的原始版本对应的master进程
kill -USR2 `more /usr/local/logs/nginx.pid.oldbin`
# 发送信号QUIT给Nginx的原始版本对应的master进程
kill -QUIT `more /usr/local/logs/nginx.pid.oldbin`

使用Nginx安装目录的make命令完成升级

sh
#将原始版本的sbin目录下的nginx进行备份
cd /usr/local/nginx/sbin
mv nginx nginxold

# 将编译后objs目录下的nginx文件,拷贝到`/usr/local/nginx/sbin`目录下
cp nginx /usr/local/nginx/sbin

# 进入到安装目录执行`make upgrade`
make upgrade

4.2 nginx配置为系统服务

sh
# vim /usr/lib/systemd/system/nginx.service

[Unit]
Description=nginx web service
Documentation=http://nginx.org/en/docs/
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true

[Install]
WantedBy=default.target

# 授权
chmod 755 /usr/lib/systemd/system/nginx.service

# 启动: 
systemctl start nginx
# 停止: 
systemctl stop nginx
# 重启: 
systemctl restart nginx
# 重新加载配置文件: 
systemctl reload nginx
# 查看nginx状态: 
systemctl status nginx
# 开机启动: 
systemctl enable nginx

4.3 Nginx命令配置到系统环境

sh
# vim /etc/profile  在最后一行添加
export PATH=$PATH:/usr/local/nginx/sbin
# 生效
source /etc/profile
# 执行命令
nginx -V

4.4 静态资源优化配置

Nginx对静态资源如何进行优化配置。这里从三个属性配置进行优化:

sendfile on;
tcp_nopush on;
tcp_nodeplay on;

sendfile

用来开启高效的文件传输模式。

语法sendfile on |off;
默认值sendfile off;
位置http、server、location...

请求静态资源的过程:客户端通过网络接口向服务端发送请求,操作系统将这些客户端的请求传递给服务器端应用程序,服务器端应用程序会处理这些请求,请求处理完成以后,操作系统还需要将处理得到的结果通过网络适配器传递回去。

tcp_nopush

该指令必须在sendfile打开的状态下才会生效,主要是用来提升网络包的传输'效率'

语法tcp_nopush on|off;
默认值tcp_nopush off;
位置http、server、location

tcp_nodelay

该指令必须在keep-alive连接开启的情况下才生效,来提高网络包传输的'实时性'

语法tcp_nodelay on|off;
默认值tcp_nodelay on;
位置http、server、location

"tcp_nopush"和”tcp_nodelay“看起来是"互斥的",那么为什么要将这两个值都打开,这个大家需要知道的是在linux2.5.9以后的版本中两者是可以兼容的,三个指令都开启的好处是,sendfile可以开启高效的文件传输模式,tcp_nopush开启可以确保在发送到客户端之前数据包已经充分“填满”, 这大大减少了网络开销,并加快了文件发送的速度。 然后,当它到达最后一个可能因为没有“填满”而暂停的数据包时,Nginx会忽略tcp_nopush参数, 然后,tcp_nodelay强制套接字发送数据。由此可知,TCP_NOPUSH可以与TCP_NODELAY一起设置,它比单独配置TCP_NODELAY具有更强的性能。

4.5 静态资源压缩

nginx可通过模块开启静态资源压缩的功能。

ngx_http_gzip_module模块
ngx_http_gzip_static_module模块
ngx_http_gunzip_module模块

Gzip指令

  1. gzip指令:该指令用于开启或者关闭gzip功能
语法gzip on|off;
默认值gzip off;
位置http、server、location...

注意只有该指令为打开状态,下面的指令才有效果

http{
   gzip on;
}
  1. gzip_types指令:该指令可以根据响应页的MIME类型选择性地开启Gzip压缩功能
语法gzip_types mime-type ...;
默认值gzip_types text/html;
位置http、server、location

所选择的值可以从mime.types文件中进行查找,也可以使用"*"代表所有。

http{
	gzip_types application/javascript;
}
  1. gzip_comp_level指令:该指令用于设置Gzip压缩程度,级别从1-9,1表示要是程度最低,要是效率最高,9刚好相反,压缩程度最高,但是效率最低最费时间。
语法gzip_comp_level level;
默认值gzip_comp_level 1;
位置http、server、location
http{
	gzip_comp_level 6;
}
  1. gzip_vary指令:该指令用于设置使用Gzip进行压缩发送是否携带“Vary:Accept-Encoding”头域的响应头部。主要是告诉接收方,所发送的数据经过了Gzip压缩处理
语法gzip_vary on|off;
默认值gzip_vary off;
位置http、server、location
  1. gzip_buffers指令:该指令用于处理请求压缩的缓冲区数量和大小。
语法gzip_buffers number size;
默认值gzip_buffers 32 4k|16 8k;
位置http、server、location

其中number:指定Nginx服务器向系统申请缓存空间个数,size指的是每个缓存空间的大小。主要实现的是申请number个每个大小为size的内存空间。这个值的设定一般会和服务器的操作系统有关,所以建议此项不设置,使用默认值即可。

gzip_buffers 4 16K;	  #缓存空间大小
  1. gzip_disable指令:针对不同种类客户端发起的请求,可以选择性地开启和关闭Gzip功能。
语法gzip_disable regex ...;
默认值
位置http、server、location

regex:根据客户端的浏览器标志(user-agent)来设置,支持使用正则表达式。指定的浏览器标志不使用Gzip.该指令一般是用来排除一些明显不支持Gzip的浏览器。

gzip_disable "MSIE [1-6]\.";
  1. gzip_http_version指令:针对不同的HTTP协议版本,可以选择性地开启和关闭Gzip功能。
语法gzip_http_version 1.0|1.1;
默认值gzip_http_version 1.1;
位置http、server、location

该指令是指定使用Gzip的HTTP最低版本,该指令一般采用默认值即可。

  1. gzip_min_length指令:该指令针对传输数据的大小,可以选择性地开启和关闭Gzip功能
语法gzip_min_length length;
默认值gzip_min_length 20;
位置http、server、location
nignx计量大小的单位:bytes[字节] / kb[千字节] / M[兆]
例如: 1024 / 10k|K / 10m|M

Gzip压缩功能对大数据的压缩效果明显,但是如果要压缩的数据比较小的化,可能出现越压缩数据量越大的情况,因此我们需要根据响应内容的大小来决定是否使用Gzip功能,响应页面的大小可以通过头信息中的Content-Length来获取。但是如何使用了Chunk编码动态压缩,该指令将被忽略。建议设置为1K或以上。

  1. gzip_proxied指令:该指令设置是否对服务端返回的结果进行Gzip压缩。
语法gzip_proxied off|expired|no-cache|
no-store|private|no_last_modified|no_etag|auth|any;
默认值gzip_proxied off;
位置http、server、location

off - 关闭Nginx服务器对后台服务器返回结果的Gzip压缩 expired - 启用压缩,如果header头中包含 "Expires" 头信息 no-cache - 启用压缩,如果header头中包含 "Cache-Control:no-cache" 头信息 no-store - 启用压缩,如果header头中包含 "Cache-Control:no-store" 头信息 private - 启用压缩,如果header头中包含 "Cache-Control:private" 头信息 no_last_modified - 启用压缩,如果header头中不包含 "Last-Modified" 头信息 no_etag - 启用压缩 ,如果header头中不包含 "ETag" 头信息 auth - 启用压缩 , 如果header头中包含 "Authorization" 头信息 any - 无条件启用压缩

配置示例

可抽取到一个单独文件,使用include将配置文件加载。

gzip on;  			  #开启gzip功能
gzip_types *;		  #压缩源文件类型,根据具体的访问资源类型设定
gzip_comp_level 6;	  #gzip压缩级别
gzip_min_length 1024; #进行压缩响应页面的最小长度,content-length
gzip_buffers 4 16K;	  #缓存空间大小
gzip_http_version 1.1; #指定压缩响应所需要的最低HTTP请求版本
gzip_vary  on;		  #往头信息中添加压缩标识
gzip_disable "MSIE [1-6]\."; #对IE6以下的版本都不进行压缩
gzip_proxied  off; #nginx作为反向代理压缩服务端返回数据的条件

Gzip和sendfile共存问题

开启sendfile以后,在读取磁盘上的静态资源文件的时候,可以减少拷贝的次数,可以不经过用户进程将静态文件通过网络设备发送出去,但是Gzip要想对资源压缩,是需要经过用户进程进行操作的。两个设置的共存可以使用ngx_http_gzip_static_module模块的gzip_static指令来解决。

gzip_static指令

gzip_static: 检查与访问资源同名的.gz文件时,response中以gzip相关的header返回.gz文件的内容。

语法gzip_static on | off | always;
默认值gzip_static off;
位置http、server、location

添加命令后,若没有添加ngx_http_gzip_static_module模块会报unknown directive "gzip_static错误

4.6 静态资源缓存

缓存、web缓存、浏览器缓存概念

缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。

Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页

浏览器缓存是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览.

浏览器缓存执行流程

HTTP协议中和页面缓存相关的字段:

header说明
Expires缓存过期的日期和时间
Cache-Control设置和缓存相关的配置信息
Last-Modified请求资源最后修改时间
ETag请求变量的实体标签的当前值,比如文件的MD5值

(1)用户首次通过浏览器发送请求到服务端获取数据,客户端是没有对应的缓存,所以需要发送request请求来获取数据;

(2)服务端接收到请求后,获取服务端的数据及服务端缓存的允许后,返回200的成功状态码并且在响应头上附上对应资源以及缓存信息;

(3)当用户再次访问相同资源的时候,客户端会在浏览器的缓存目录中查找是否存在响应的缓存文件

(4)如果没有找到对应的缓存文件,则走(2)步

(5)如果有缓存文件,接下来对缓存文件是否过期进行判断,过期的判断标准是(Expires),

(6)如果没有过期,则直接从本地缓存中返回数据进行展示

(7)如果Expires过期,接下来需要判断缓存文件是否发生过变化

(8)判断的标准有两个,一个是ETag(Entity Tag),一个是Last-Modified

(9)判断结果是未发生变化,则服务端返回304,直接从缓存文件中获取数据

(10)如果判断是发生了变化,重新从服务端获取数据,并根据缓存协商(服务端所设置的是否需要进行缓存数据的设置)来进行数据缓存。

浏览器缓存相关指令

expires指令

expires:该指令用来控制页面缓存的作用。可以通过该指令控制HTTP应答中的“Expires"和”Cache-Control"

语法expires [modified] time
expires epoch|max|off;
默认值expires off;
位置http、server、location

time:可以整数也可以是负数,指定过期时间,如果是负数,Cache-Control则为no-cache,如果为整数或0,则Cache-Control的值为max-age=time;

epoch: 指定Expires的值为'1 January,1970,00:00:01 GMT'(1970-01-01 00:00:00),Cache-Control的值no-cache

max:指定Expires的值为'31 December2037 23:59:59GMT' (2037-12-31 23:59:59) ,Cache-Control的值为10年

off:默认不缓存。

add_header指令

add_header指令是用来添加指定的响应头和响应值。

语法add_header name value [always];
默认值
位置http、server、location...

Cache-Control作为响应头信息,可以设置如下值:

缓存响应指令:

Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
指令说明
must-revalidate可缓存但必须再向源服务器进行确认
no-cache缓存前必须确认其有效性
no-store不缓存请求或响应的任何内容
no-transform代理不可更改媒体类型
public可向任意方提供响应的缓存
private仅向特定用户返回响应
proxy-revalidate要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=<秒>响应最大Age值
s-maxage=<秒>公共缓存服务器响应的最大Age值

4.7 解决跨域问题

浏览器的同源策略:是一种约定,是浏览器最核心也是最基本的安全功能,如果浏览器少了同源策略,则浏览器的正常功能可能都会受到影响。

同源: 协议、域名(IP)、端口相同即为同源

使用add_header指令,该指令可以用来添加一些头信息

语法add_header name value...
默认值
位置http、server、location

此处用来解决跨域问题,需要添加两个头信息,一个是Access-Control-Allow-Origin,Access-Control-Allow-Methods

Access-Control-Allow-Origin: 直译过来是允许跨域访问的源地址信息,可以配置多个(多个用逗号分隔),也可以使用*代表所有源

Access-Control-Allow-Methods:直译过来是允许跨域访问的请求方式,值可以为 GET POST PUT DELETE...,可以全部设置,也可以根据需要设置,多个用逗号分隔

具体配置方式

location /getUser{
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;
    default_type application/json;
    return 200 '{"id":1,"name":"TOM","age":18}';
}

4.8 静态资源防盗链

资源盗链指的是此内容不在自己服务器上,而是通过技术手段,绕过别人的限制将别人的内容放到自己页面上最终展示给用户。以此来盗取大网站的空间和流量。简而言之就是用别人的东西成就自己的网站。

Referer限制方式

valid_referers:nginx会通就过查看referer自动和valid_referers后面的内容进行匹配,如果匹配到了就将$invalid_referer变量置0,如果没有匹配到,则将$invalid_referer变量置为1,匹配的过程中不区分大小写。

语法valid_referers none|blocked|server_names|string...
默认值
位置server、location

none: 如果Header中的Referer为空,允许访问

blocked:在Header中的Referer不为空,但是该值被防火墙或代理进行伪装过,如不带"http://" 、"https://"等协议头的资源允许访问。

server_names:指定具体的域名或者IP

string: 可以支持正则表达式和*的字符串。如果是正则表达式,需要以~开头表示,例如

// 可对目录下资源进行操作 location /images
location ~*\.(png|jpg|gif){
           valid_referers none blocked www.baidu.com 192.168.200.222 *.example.com example.*  www.example.org  ~\.google\.;
           if ($invalid_referer){
                return 403;
                // 可通过rewrite 返回没有权限的提示图
                // rewrite ^/ http://www.web.com/images/forbidden.png;
           }
           root /usr/local/nginx/html;

}

4.9 添加模块

sh
# 查询当前Nginx的配置参数
nginx -V


# 将nginx安装目录下sbin目录中的nginx二进制文件进行更名
cd /usr/local/nginx/sbin
mv nginx nginxold


# 进入Nginx的安装目录
cd /root/nginx/core/nginx-1.16.1


# 执行make clean清空之前编译的内容
make clean


# 使用configure来配置参数 添加模块,以 http_gzip_static_module 为例
./configure --with-http_gzip_static_module

# 使用make命令进行编译
make

# 将objs目录下的nginx二进制执行文件移动到nginx安装目录下的sbin目录中
mv objs/nginx /usr/local/nginx/sbin


# 执行更新命令
make upgrade

4.10 Nginx安全控制

安全隔离:

通过代理分开了客户端到应用程序服务器端的连接,实现了安全措施。在反向代理之前设置防火墙,仅留一个入口供代理服务器访问。

使用SSL对流量进行加密

将http请求转变成https请求,https是身披SSL外壳的http.

HTTPS是一种通过计算机网络进行安全通信的传输协议。它经由HTTP进行通信,利用SSL/TLS建立全通信,加密数据包,确保数据的安全性。

SSL(Secure Sockets Layer)安全套接层

TLS(Transport Layer Security)传输层安全

上述这两个是为网络通信提供安全及数据完整性的一种安全协议,TLS和SSL在传输层和应用层对网络连接进行加密。

Nginx要想使用SSL,需要满足一个条件即需要添加一个模块--with-http_ssl_module,而该模块在编译的过程中又需要OpenSSL的支持

SSL指令

ssl

该指令用来在指定的服务器开启HTTPS,可以使用 listen 443 ssl,后面这种方式更通用些。

语法ssl on | off;
默认值ssl off;
位置http、server
server{
	listen 443 ssl;
}
ssl_certificate

为当前这个虚拟主机指定一个带有PEM格式证书的证书。

语法ssl_certificate file;
默认值
位置http、server
ssl_certificate_key

该指令用来指定PEM secret key文件的路径

语法ssl_ceritificate_key file;
默认值
位置http、server
ssl_session_cache

该指令用来配置用于SSL会话的缓存

语法ssl_sesion_cache off|none|[builtin[:size]] [shared:name:size]
默认值ssl_session_cache none;
位置http、server

off:禁用会话缓存,客户端不得重复使用会话

none:禁止使用会话缓存,客户端可以重复使用,但是并没有在缓存中存储会话参数

builtin:内置OpenSSL缓存,仅在一个工作进程中使用。

shared:所有工作进程之间共享缓存,缓存的相关信息用name和size来指定

ssl_session_timeout

开启SSL会话功能后,设置客户端能够反复使用储存在缓存中的会话参数时间。

语法ssl_session_timeout time;
默认值ssl_session_timeout 5m;
位置http、server
ssl_ciphers

指出允许的密码,密码指定为OpenSSL支持的格式

语法ssl_ciphers ciphers;
默认值ssl_ciphers HIGH:!aNULL:!MD5;
位置http、server

可以使用openssl ciphers查看openssl支持的格式。

ssl_prefer_server_ciphers

该指令指定是否服务器密码优先客户端密码

语法ssl_perfer_server_ciphers on|off;
默认值ssl_perfer_server_ciphers off;
位置http、server

生成证书

sh
# 方式一:使用阿里云/腾讯云等第三方服务进行购买。
# 方式二:使用openssl生成证书
mkdir /root/cert
cd /root/cert
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

4.11 反向代理系统调优

反向代理值Buffer和Cache

Buffer翻译过来是"缓冲",Cache翻译过来是"缓存"。

相同点:
两种方式都是用来提供IO吞吐效率,都是用来提升Nginx代理的性能。
不同点:
缓冲主要用来解决不同设备之间数据传递速度不一致导致的性能低的问题,缓冲中的数据一旦此次操作完成后,就可以删除。
缓存主要是备份,将被代理服务器的数据缓存一份到代理服务器,这样的话,客户端再次获取相同数据的时候,就只需要从代理服务器上获取,效率较高,缓存中的数据可以重复使用,只有满足特定条件才会删除.

Proxy Buffer相关指令

proxy_buffering

该指令用来开启或者关闭代理服务器的缓冲区;

语法proxy_buffering on|off;
默认值proxy_buffering on;
位置http、server、location
proxy_buffers

该指令用来指定单个连接从代理服务器读取响应的缓存区的个数和大小。

语法proxy_buffers number size;
默认值proxy_buffers 8 4k | 8K;(与系统平台有关)
位置http、server、location

number:缓冲区的个数

size:每个缓冲区的大小,缓冲区的总大小就是number*size

proxy_buffer_size

该指令用来设置从被代理服务器获取的第一部分响应数据的大小。保持与proxy_buffers中的size一致即可,当然也可以更小。

语法proxy_buffer_size size;
默认值proxy_buffer_size 4k | 8k;(与系统平台有关)
位置http、server、location
proxy_busy_buffers_size

该指令用来限制同时处于BUSY状态的缓冲总大小。

语法proxy_busy_buffers_size size;
默认值proxy_busy_buffers_size 8k|16K;
位置http、server、location
proxy_temp_path

当缓冲区存满后,仍未被Nginx服务器完全接受,响应数据就会被临时存放在磁盘文件上,该指令设置文件路径

语法proxy_temp_path path;
默认值proxy_temp_path proxy_temp;
位置http、server、location

注意path最多设置三层。

proxy_temp_file_write_size

该指令用来设置磁盘上缓冲文件的大小。

语法proxy_temp_file_write_size size;
默认值proxy_temp_file_write_size 8K|16K;
位置http、server、location

通用网站的配置

proxy_buffering on;
proxy_buffer_size 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

根据项目的具体内容进行相应的调节。

4.12 Nginx制作下载站点

网站http://nginx.org/download/主要就是用来提供用户来下载相关资源的网站,就叫做下载网站。

nginx使用模块ngx_http_autoindex_module来实现下载站点。该模块处理以斜杠("/")结尾的请求,并生成目录列表。

nginx编译的时候会自动加载该模块,但是该模块默认是关闭的,我们需要使用下来指令来完成对应的配置

指令

autoindex

启用或禁用目录列表输出

语法autoindex on|off;
默认值autoindex off;
位置http、server、location
autoindex_exact_size

对应HTLM格式,指定是否在目录列表展示文件的详细大小

默认为on,显示出文件的确切大小,单位是bytes。 改为off后,显示出文件的大概大小,单位是kB或者MB或者GB

语法autoindex_exact_size on|off;
默认值autoindex_exact_size on;
位置http、server、location
autoindex_format

设置目录列表的格式

语法autoindex_format html|xml|json|jsonp;
默认值autoindex_format html;
位置http、server、location

注意:该指令在1.7.9及以后版本中出现

autoindex_localtime

对应HTML格式,是否在目录列表上显示时间。

默认为off,显示的文件时间为GMT时间。 改为on后,显示的文件时间为文件的服务器时间

语法autoindex_localtime on | off;
默认值autoindex_localtime off;
位置http、server、location
配置方式
location /download{
    root /usr/local;
    autoindex on;
    autoindex_exact_size on;
    autoindex_format html;
    autoindex_localtime on;
}

4.13 用户认证模块

对应系统资源的访问,我们往往需要限制谁能访问,谁不能访问。这块就是我们通常所说的认证部分,认证需要做的就是根据用户输入的用户名和密码来判定用户是否为合法用户,如果是则放行访问,如果不是则拒绝访问。

Nginx对应用户认证这块是通过ngx_http_auth_basic_module模块来实现的,它允许通过使用"HTTP基本身份验证"协议验证用户名和密码来限制对资源的访问。默认情况下nginx是已经安装了该模块,如果不需要则使用--without-http_auth_basic_module。

auth_basic:使用“ HTTP基本认证”协议启用用户名和密码的验证

语法auth_basic string|off;
默认值auth_basic off;
位置http,server,location,limit_except

开启后,服务端会返回401,指定的字符串会返回到客户端,给用户以提示信息,但是不同的浏览器对内容的展示不一致。

(2)auth_basic_user_file:指定用户名和密码所在文件

语法auth_basic_user_file file;
默认值
位置http,server,location,limit_except

指定文件路径,该文件中的用户名和密码的设置,密码需要进行加密。可以采用工具自动生成

实现步骤:

1.nginx.conf添加如下内容

location /download{
    root /usr/local;
    autoindex on;
    autoindex_exact_size on;
    autoindex_format html;
    autoindex_localtime on;
    auth_basic 'please input your auth';
    auth_basic_user_file htpasswd;
}

2.我们需要使用htpasswd工具生成

yum install -y httpd-tools
htpasswd -c /usr/local/nginx/conf/htpasswd username //创建一个新文件记录用户名和密码
htpasswd -b /usr/local/nginx/conf/htpasswd username password //在指定文件新增一个用户名和密码
htpasswd -D /usr/local/nginx/conf/htpasswd username //从指定文件删除一个用户信息
htpasswd -v /usr/local/nginx/conf/htpasswd username //验证用户名和密码是否正确

4.14 ngx_lua模块

淘宝开发的ngx_lua模块通过将lua解释器集成进Nginx,可以采用lua脚本实现业务逻辑,由于lua的紧凑、快速以及内建协程,所以在保证高并发服务能力的同时极大地降低了业务逻辑实现成本

添加模块

方式一:
  1. LuaJIT是采用C语言编写的Lua代表的解释器。

官网地址为:http://luajit.org/

在官网上找到对应的下载地址:http://luajit.org/download/LuaJIT-2.0.5.tar.gz

在centos上使用wget来下载: wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz

将下载的资源进行解压: tar -zxf LuaJIT-2.0.5.tar.gz

进入解压的目录: cd LuaJIT-2.0.5

执行编译和安装: make && make install

  1. 下载lua-nginx-module

下载地址:https://github.com/openresty/lua-nginx-module/archive/v0.10.16rc4.tar.gz

在centos上使用wget来下载: wget https://github.com/openresty/lua-nginx-module/archive/v0.10.16rc4.tar.gz

将下载的资源进行解压: tar -zxf lua-nginx-module-0.10.16rc4.tar.gz

更改目录名:mv lua-nginx-module-0.10.16rc4 lua-nginx-module

导入环境变量,告诉Nginx去哪里找luajit

export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0

进入Nginx的目录执行如下命令:

./configure --prefix=/usr/local/nginx --add-module=../lua-nginx-module
make && make install

注意事项:

(1)如果启动Nginx出现 error while loading shared libraries: libluajit-5.1.so.2,需要设置软连接

ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2

(2)如果启动Nginx出现lua_load_resty_core failed to load the resty.core module,resty.core是openrestry的核心模块,对其下的很多函数进行了优化等工作。以前的版本默认不会把该模块编译进去,所以需要使用的话,我们得手动安装,或者禁用就可以。但是最新的lua-nginx-module模块已经强制性安装了该模块,所以此处因为缺少resty模块导致的报错信息。

需要下载对应得模块或者金用restry模块,禁用方式:

http{
	lua_load_resty_core off;
}
方式二:

使用OpenRestry

ngx_lua使用

使用Lua编写Nginx脚本的基本构建块是指令。指令用于指定何时运行用户Lua代码以及如何使用结果。执行指令的顺序为:

先来解释下*的作用

*:无 , 即 xxx_by_lua ,指令后面跟的是 lua指令
*:_file,即 xxx_by_lua_file 指令后面跟的是 lua文件
*:_block,即 xxx_by_lua_block 在0.9.17版后替换init_by_lua_file
init_by_lua*
该指令在每次Nginx重新加载配置时执行,可以用来完成一些耗时模块的加载,或者初始化一些全局配置。
init_worker_by_lua*
该指令用于启动一些定时任务,如心跳检查、定时拉取服务器配置等。
set_by_lua*
该指令只要用来做变量赋值,这个指令一次只能返回一个值,并将结果赋值给Nginx中指定的变量。
rewrite_by_lua*
该指令用于执行内部URL重写或者外部重定向,典型的如伪静态化URL重写,本阶段在rewrite处理阶段的最后默认执行。
access_by_lua*
该指令用于访问控制。例如,如果只允许内网IP访问。
content_by_lua*
该指令是应用最多的指令,大部分任务是在这个阶段完成的,其他的过程往往为这个阶段准备数据,正式处理基本都在本阶段。
header_filter_by_lua*
该指令用于设置应答消息的头部信息。
body_filter_by_lua*
该指令是对响应数据进行过滤,如截断、替换。
log_by_lua*
该指令用于在log请求处理阶段,用Lua代码处理日志,但并不替换原有log处理。
balancer_by_lua*
该指令主要的作用是用来实现上游服务器的负载均衡器算法
ssl_certificate_by_*
该指令作用在Nginx和下游服务开始一个SSL握手操作时将允许本配置项的Lua代码。

ngx_lua操作Redis

Nginx支持3种方法访问Redis,分别是HttpRedis模块、HttpRedis2Module、lua-resty-redis库。这三种方式中HttpRedis模块提供的指令少,功能单一,适合做简单缓存,HttpRedis2Module模块比HttpRedis模块操作更灵活,功能更强大。而Lua-resty-redis库是OpenResty提供的一个操作Redis的接口库,可根据自己的业务情况做一些逻辑处理,适合做复杂的业务逻辑。

lua-resty-redis提供了访问Redis的详细API,包括创建对接、连接、操作、数据处理等。这些API基本上与Redis的操作一一对应。
(1)redis = require "resty.redis"
(2)new
	语法: redis,err = redis:new(),创建一个Redis对象。
(3)connect
	语法:ok,err=redis:connect(host,port[,options_table]),设置连接Redis的连接信息。
	ok:连接成功返回 1,连接失败返回nil
	err:返回对应的错误信息
(4)set_timeout
	语法: redis:set_timeout(time) ,设置请求操作Redis的超时时间。
(5)close
	语法: ok,err = redis:close(),关闭当前连接,成功返回1,失败返回nil和错误信息
(6)redis命令对应的方法
	在lua-resty-redis中,所有的Redis命令都有自己的方法,方法名字和命令名字相同,只是全部为小写。
location / {
    default_type "text/html";
    content_by_lua_block{
        local redis = require "resty.redis" -- 引入Redis
        local redisObj = redis:new()  --创建Redis对象
        redisObj:set_timeout(1000) --设置超时数据为1s
        local ok,err = redisObj:connect("192.168.200.1",6379) --设置redis连接信息
        if not ok then --判断是否连接成功
         ngx.say("failed to connection redis",err)
         return
        end
        
        -- 请注意这里 auth 的调用过程
        local count
        count, err = red:get_reused_times()
        if 0 == count then
            ok, err = red:auth("admin")
            if not ok then
                ngx.say("failed to auth: ", err)
                return
            end
        elseif err then
            ngx.say("failed to get reused times: ", err)
            return
        end
        
        -- 连接池大小是100个,并且设置最大的空闲时间是 10 秒
        local ok, err = red:set_keepalive(10000, 100)
        if not ok then
            ngx.say("failed to set keepalive: ", err)
            return
        end
        
        ok,err = redisObj:set("username","TOM")--存入数据
        if not ok then --判断是否存入成功
         ngx.say("failed to set username",err)
         return
        end
        local res,err = redisObj:get("username") --从redis中获取数据
        ngx.say(res)	--将数据写会消息体中
        redisObj:close()
    }
}

ngx_lua操作Mysql

MySQL是一个使用广泛的关系型数据库。在ngx_lua中,MySQL有两种访问模式,分别是使

(1)用ngx_lua模块和lua-resty-mysql模块:这两个模块是安装OpenResty时默认安装的。

(2)使用drizzle_nginx_module(HttpDrizzleModule)模块:需要单独安装,这个库现不在OpenResty中。

lua-resty-mysql

lua-resty-mysql是OpenResty开发的模块,使用灵活、功能强大,适合复杂的业务场景,同时支持存储过程的访问。

(1)引入"resty.mysql"模块
	local mysql = require "resty.mysql"
(2)new
	创建一个MySQL连接对象,遇到错误时,db为nil,err为错误描述信息
	语法: db,err = mysql:new()
(3)connect
	尝试连接到一个MySQL服务器
	语法:ok,err=db:connect(options),options是一个参数的Lua表结构,里面包含数据库连接的相关信息
    host:服务器主机名或IP地址
    port:服务器监听端口,默认为3306
    user:登录的用户名
    password:登录密码
    database:使用的数据库名
(4)set_timeout
	设置子请求的超时时间(ms),包括connect方法
	语法:db:set_timeout(time)
(5)close
	关闭当前MySQL连接并返回状态。如果成功,则返回1;如果出现任何错误,则将返回nil和错误描述。
	语法:db:close()
(6)send_query
	异步向远程MySQL发送一个查询。如果成功则返回成功发送的字节数;如果错误,则返回nil和错误描述
	语法:bytes,err=db:send_query(sql)
(7)read_result
	从MySQL服务器返回结果中读取一行数据。res返回一个描述OK包或结果集包的Lua表,语法:
	res, err, errcode, sqlstate = db:read_result() 
	res, err, errcode, sqlstate = db:read_result(rows) :rows指定返回结果集的最大值,默认为4
	如果是查询,则返回一个容纳多行的数组。每行是一个数据列的key-value对,如

    {
      {id=1,username="TOM",birthday="1988-11-11",salary=10000.0},
      {id=2,username="JERRY",birthday="1989-11-11",salary=20000.0}
    }
	如果是增删改,则返回类上如下数据
    {
    	insert_id = 0,
    	server_status=2,
    	warning_count=1,
    	affected_rows=2,
    	message=nil
    }
	返回值:
		res:操作的结果集
		err:错误信息
		errcode:MySQL的错误码,比如1064
		sqlstate:返回由5个字符组成的标准SQL错误码,比如42000
location /{
    content_by_lua_block{
        local mysql = require "resty.mysql"
        local db = mysql:new()
        local ok,err = db:connect{
            host="192.168.200.111",
            port=3306,
            user="root",
            password="123456",
            database="nginx_db"
        }
        db:set_timeout(1000)

        db:send_query("select * from users where id =1")
        local res,err,errcode,sqlstate = db:read_result()
        	ngx.say(res[1].id..","..res[1].username..","..res[1].birthday..","..res[1].salary)
    	--local res,err,errcode,sqlstate = db:query("insert into users(id,username,birthday,salary) values(null,'zhangsan','2020-11-11',32222.0)")
        --local res,err,errcode,sqlstate = db:query("update users set username='lisi' where id = 6")
        --local res,err,errcode,sqlstate = db:query("delete from users where id = 6")
        db:close()
    }

}

使用lua-cjson处理查询结果

将table类型的数据转换成json字符串

步骤一:引入cjson

local cjson = require "cjson"

步骤二:调用cjson的encode方法进行类型转换

cjson.encode(res)

步骤三:使用

location /{
    content_by_lua_block{

        local mysql = require "resty.mysql"
        local cjson = require "cjson"

        local db = mysql:new()

        local ok,err = db:connect{
            host="192.168.200.111",
            port=3306,
            user="root",
            password="123456",
            database="nginx_db"
        }
        db:set_timeout(1000)

        --db:send_query("select * from users where id = 2")
        db:send_query("select * from users")
        local res,err,errcode,sqlstate = db:read_result()
        ngx.say(cjson.encode(res))
         for i,v in ipairs(res) do
       ngx.say(v.id..","..v.username..","..v.birthday..","..v.salary)
        end
    	db:close()
    }

}

4.15 openResty操作

引入lua处理逻辑

openresty 1.9.3.1 及以下版本,请使用 content_by_lua 命令;在 openresty 1.9.3.2 以上,content_by_lua 改成了 content_by_lua_block。可使用 nginx -V 命令查看版本号

properties
location / {
            #root   html;
            #index  index.html index.htm;
			default_type text/html;
			content_by_lua_block {
				ngx.say("hello world");
			}
        }
properties
location / {
            #root   html;
            #index  index.html index.htm;
			default_type text/html;
			content_by_lua_file /usr/local/openresty/nginx/conf/my.lua;
        }

获取http请求信息

  • 获取uri参数

    获取一个 uri 有两个方法:ngx.req.get_uri_args、ngx.req.get_post_args,二者主要的区别是参数来源有区别

    lua
    -- 获取get请求参数
    local arg = ngx.req.get_uri_args()
    for k,v in pairs(arg) do
       ngx.say("[GET ] key:", k, " v:", v)
       ngx.say("<br>")
    end
    
    -- 获取post请求时 请求参数
    ngx.req.read_body() -- 解析 body 参数之前一定要先读取 body
    local arg = ngx.req.get_post_args()
    for k,v in pairs(arg) do
       ngx.say("[POST] key:", k, " v:", v)
        ngx.say("<br>")
    end
  • 获取header

    lua
    -- 获取header
    local headers = ngx.req.get_headers()  
    for k,v in pairs(headers) do
       ngx.say("[header] name:", k, " v:", v)
        ngx.say("<br>")
    end
  • 获取body

    lua
    -- 获取body信息
    local data = ngx.req.get_body_data()
    ngx.say(data)

    ngx.req.get_body_data() 读请求体,会偶尔出现读取不到直接返回 nil 的情况。如果请求体尚未被读取,请先调用 ngx.req.read_body (或打开 lua_need_request_body 选项强制本模块读取请求体,此方法不推荐)。

模板渲染

  • 导入lua-resty-template,

    下载 http://luarocks.org/modules/bungle/lua-resty-template

    将template.lua文件复制到openresty/lualib/resty/目录下。

  • 修改nginx.conf

    lua
    --设置模板路径:
    set $template_root /usr/local/openresty/nginx/html/templates;
    --设置mimeType类型:
    default_type text/html;
    -- 导入lua文件:
    content_by_lua_file /usr/local/openresty/nginx/conf/*.lua
  • lua脚本

    lua
    -- 1
    local template = require "resty.template"
    content={ 
    	message = "Hello, World!",
    	names = {"james","fox","tony"}
    }
    template.render("demo.html", content)  
    
    -- 2
    local template = require "resty.template"  
    local redis = require "resty.redis_iresty"
    local red = redis:new()
    local msg = red:get("num")
    if ngx.null==msg then
    	return ngx.say("获取库存失败");
    end
    
    local context = {  
        title = "品优购",
    	-- 从redis中获取库存信息,在页面中显示
    	num=msg
    }  
    local request_uri = ngx.var.request_uri
    
    template.render(string.sub(request_uri,2),context);

lua-kafka

下载:

将resty⽬录解压到openresty的安装⽬录/lualib下

lua
location / {
	root html;
	index index.html index.htm;
	log_by_lua ' 
        local cjson = require "cjson" 
        local producer = require "resty.kafka.producer" 
        local broker_list = { 
        { host = "39.98.133.153", port = 9103 }, 
        } 
        local log_json = {} 
        log_json["message"]="this is a test" 
        log_json["from"]="nginx" 
        log_json["rid"]="a"
        log_json["sid"]="b"
        log_json["tid"]="c"
        local message = cjson.encode(log_json); 
        local bp = producer:new(broker_list, { producer_type = "async" }) 
        -- 发送⽇志消息,send第⼆个参数key,⽤于kafka路由控制: 
        -- key为nill(空)时,⼀段时间向同⼀partition写⼊数据 
        -- 指定key,按照key的hash写⼊到对应的partition 
        local ok, err = bp:send("demo", nil, message) 

        if not ok then 
            ngx.log(ngx.ERR, "kafka send err:", err) 
            return 
        end 
	'; 
 }

五、安装

5.1 常规安装

  • 安装gcc环境 yum -y install gcc-c++

  • 关闭SELINX vim /etc/selinux/config SELINUX=disabled

  • 在linux上安装pcre库,nginx的http模块使用pcre来解析正则表达式. yum install -y pcre pcre-devel

  • 安装zlib库,zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip. yum install -y zlib zlib-devel

  • 安装openssl库,OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,nginx支持https(在ssl协议上传输http) yum install -y openssl openssl-devel

  • 安装一:

    sh
    wget http://nginx.org/download/nginx-1.16.1.tar.gz
    
    mkdir -p nginx/core
    mv nginx-1.16.1.tar.gz nginx/core
    
    tar -xzf nginx-1.16.1.tar.gz
    
    ./configure
    
    make
    
    make install
  • 安装二:

    sh
    sudo yum  install -y yum-utils
    
    vim /etc/yum.repos.d/nginx.repo
    
    yum list | grep nginx
    
    yun install -y nginx
    
    whereis nginx
    [nginx-stable]
    name=nginx stable repo
    baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
    gpgcheck=1
    enabled=1
    gpgkey=https://nginx.org/keys/nginx_signing.key
    module_hotfixes=true
    
    [nginx-mainline]
    name=nginx mainline repo
    baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
    gpgcheck=1
    enabled=0
    gpgkey=https://nginx.org/keys/nginx_signing.key
    module_hotfixes=true

5.2 nginx复杂安装

nginx源码解压目录

auto:存放的是编译相关的脚本

CHANGES:版本变更记录

CHANGES.ru:俄罗斯文的版本变更记录

conf:nginx默认的配置文件

configure:nginx软件的自动脚本程序,是一个比较重要的文件,作用如下:

​ (1)检测环境及根据环境检测结果生成C代码

​ (2)生成编译代码需要的Makefile文件

contrib:存放的是几个特殊的脚本文件,其中README中对脚本有着详细的说明

html:存放的是Nginx自带的两个html页面,访问Nginx的首页和错误页面

LICENSE:许可证的相关描述文件

man:nginx的man手册

README:Nginx的阅读指南

src:Nginx的源代码

编译参数配置

sh
# 指向Nginx的安装目录,默认值为/usr/local/nginx   
--prefix=PATH
# 指向(执行)程序文件(nginx)的路径,默认值为<prefix>/sbin/nginx
--sbin-path=PATH
# 指向Nginx动态模块安装目录,默认值为<prefix>/modules
--modules-path=PATH
# 指向配置文件(nginx.conf)的路径,默认值为<prefix>/conf/nginx.conf
--conf-path=PATH
# 指向错误日志文件的路径,默认值为<prefix>/logs/error.log
--error-log-path=PATH 
# 指向访问日志文件的路径,默认值为<prefix>/logs/access.log
--http-log-path=PATH  
# 指向Nginx启动后进行ID的文件路径,默认值为<prefix>/logs/nginx.pid
--pid-path=PATH
# 指向Nginx锁文件的存放路径,默认值为<prefix>/logs/nginx.lock
--lock-path=PATH
# 加入第三方链接时需要的参数。编译之后nginx最终的可执行二进制文件是由编译后的目标文件和一些第三方的库链接生成的。如果想要将某个库链接到nginx中,就需要指定–with-ld-opt=目标库名-目标库路径
–with-ld-opt
# 将nginx需要打印debug调试级别日志的代码编译进nginx,这样才可以通过修改配置文件将调试日志打印出来,便于定位服务问题 
–with-debug


# 配置示例
./configure --prefix=/usr/local/nginx \
--sbin-path=/usr/local/nginx/sbin/nginx \
--modules-path=/usr/local/nginx/modules \
--conf-path=/usr/local/nginx/conf/nginx.conf \
--error-log-path=/usr/local/nginx/logs/error.log \
--http-log-path=/usr/local/nginx/logs/access.log \
--pid-path=/usr/local/nginx/logs/nginx.pid \
--lock-path=/usr/local/nginx/logs/nginx.lock

卸载nginx

sh
./nginx -s stop
rm -rf /usr/local/nginx
make clean

nginx目录

conf:nginx所有配置文件目录

​ CGI(Common Gateway Interface)通用网关【接口】,主要解决的问题是从客户端发送一个请求和数据,服务端获取到请求和数据后可以调用调用CGI【程序】处理及相应结果给客户端的一种标准规范。

​ fastcgi.conf:fastcgi相关配置文件

​ fastcgi.conf.default:fastcgi.conf的备份文件

​ fastcgi_params:fastcgi的参数文件

​ fastcgi_params.default:fastcgi的参数备份文件

​ scgi_params:scgi的参数文件

​ scgi_params.default:scgi的参数备份文件

​ uwsgi_params:uwsgi的参数文件

​ uwsgi_params.default:uwsgi的参数备份文件

​ mime.types:记录的是HTTP协议中的Content-Type的值和文件后缀名的对应关系

​ mime.types.default:mime.types的备份文件

​ nginx.conf:这个是Nginx的核心配置文件,这个文件非常重要,也是我们即将要学习的重点

​ nginx.conf.default:nginx.conf的备份文件

​ koi-utf、koi-win、win-utf这三个文件都是与编码转换映射相关的配置文件,用来将一种编码转换成另一种编码

html:存放nginx自带的两个静态的html页面

​ 50x.html:访问失败后的失败页面

​ index.html:成功访问的默认首页

logs:记录入门的文件,当nginx服务器启动后,这里面会有 access.log error.log 和nginx.pid三个文件出现。

sbin:是存放执行程序文件nginx

​ nginx是用来控制Nginx的启动和停止等相关的命令。

5.3 docker安装

shell
# 拉取镜像
docker pull nginx
# 创建容器
docker run -di --name=mynginx -p 80:80 nginx

5.4 安装OpenResty

  • 添加openresty 仓库

    shell
    yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
    # 如果提示命令不存在
    yum install -y yum-utils
  • 安装OpenResty

    shell
    yum install -y openresty
    # 安装opm管理工具
    yum install -y openresty-opm
    
    
    (1) 下载OpenResty:https://openresty.org/download/openresty-1.15.8.2.tar.gz
    (2)使用wget下载: wget https://openresty.org/download/openresty-1.15.8.2.tar.gz
    (3)解压缩: tar -zxf openresty-1.15.8.2.tar.gz
    (4)进入OpenResty目录: cd openresty-1.15.8.2
    (5) 执行命令:./configure
    (6) 执行命令:make && make install
    (7)进入OpenResty的目录,找到nginx:cd /usr/local/openresty/nginx/
    (8)在conf目录下的nginx.conf添加如下内容
    location /lua{
        default_type 'text/html';
        content_by_lua 'ngx.say("<h1>HELLO,OpenRestry</h1>")';
    }
    (9)在sbin目录下启动nginx

5.5 nginx高可用

使用Keepalived可以解决多个nginx的部署ip的问题。将多个nginx映射到同一虚拟ip提供服务。

Keepalived 软件由 C 编写的,最初是专为 LVS 负载均衡软件设计的,Keepalived 软件主要是通过 VRRP 协议实现高可用功能。

VRRP

VRRP(Virtual Route Redundancy Protocol)协议,翻译过来为虚拟路由冗余协议。VRRP协议将两台或多台路由器设备虚拟成一个设备,对外提供虚拟路由器IP,而在路由器组内部,如果实际拥有这个对外IP的路由器如果工作正常的话就是MASTER,MASTER实现针对虚拟路由器IP的各种网络功能。其他设备不拥有该虚拟IP,状态为BACKUP,处了接收MASTER的VRRP状态通告信息以外,不执行对外的网络功能。当主机失效时,BACKUP将接管原先MASTER的网络功能。

从上面的介绍信息获取到的内容就是VRRP是一种协议,那这个协议是用来干什么的?

1.选择协议

VRRP可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台。其中的虚拟路由即Virtual路由是由VRRP路由群组创建的一个不真实存在的路由,这个虚拟路由也是有对应的IP地址。而且VRRP路由1和VRRP路由2之间会有竞争选择,通过选择会产生一个Master路由和一个Backup路由。

2.路由容错协议

Master路由和Backup路由之间会有一个心跳检测,Master会定时告知Backup自己的状态,如果在指定的时间内,Backup没有接收到这个通知内容,Backup就会替代Master成为新的Master。Master路由有一个特权就是虚拟路由和后端服务器都是通过Master进行数据传递交互的,而备份节点则会直接丢弃这些请求和数据,不做处理,只是去监听Master的状态

keepalived的安装

步骤1:从官方网站下载keepalived,官网地址https://keepalived.org/
步骤2:将下载的资源上传到服务器
	keepalived-2.0.20.tar.gz
步骤3:创建keepalived目录,方便管理资源
	mkdir keepalived
步骤4:将压缩文件进行解压缩,解压缩到指定的目录
	tar -zxf keepalived-2.0.20.tar.gz -C keepalived/
步骤5:对keepalived进行配置,编译和安装
	cd keepalived/keepalived-2.0.20
	./configure --sysconf=/etc --prefix=/usr/local
	make && make install

安装完成后,有两个文件需要我们认识下,一个是 /etc/keepalived/keepalived.conf(keepalived的系统配置文件,我们主要操作的就是该文件),一个是/usr/local/sbin目录下的keepalived,是系统配置脚本,用来启动和关闭keepalived

Keepalived配置文件介绍

global全局部分:
global_defs {
   #通知邮件,当keepalived发送切换时需要发email给具体的邮箱地址
   notification_email {
     tom@itcast.cn
     jerry@itcast.cn
   }
   #设置发件人的邮箱信息
   notification_email_from zhaomin@itcast.cn
   #指定smpt服务地址
   smtp_server 192.168.200.1
   #指定smpt服务连接超时时间
   smtp_connect_timeout 30
   #运行keepalived服务器的一个标识,可以用作发送邮件的主题信息
   router_id LVS_DEVEL
   
   #默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)
   vrrp_skip_check_adv_addr
   #严格遵守VRRP协议。
   vrrp_strict
   #在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。默认是0
   vrrp_garp_interval 0
   #在一个网卡上每组na消息之间的延迟时间,默认为0
   vrrp_gna_interval 0
}
VRRP部分,该部分可以包含以下四个子模块
1. vrrp_script
2. vrrp_sync_group
3. garp_group
4. vrrp_instance
我们会用到第一个和第四个,
#设置keepalived实例的相关信息,VI_1为VRRP实例名称
vrrp_instance VI_1 {
    state MASTER  		#有两个值可选MASTER主 BACKUP备 在用HA的时候最好master 和backup的state都设置成backup 让其通过priority来竞争。
    interface ens33		#vrrp实例绑定的接口,用于发送VRRP包[当前服务器使用的网卡名称]
    virtual_router_id 51#指定VRRP实例ID,范围是0-255
    priority 100		#指定优先级,优先级高的将成为MASTER
    advert_int 1		#指定发送VRRP通告的间隔,单位是秒
    authentication {	#vrrp之间通信的认证信息
        auth_type PASS	#指定认证方式。PASS简单密码认证(推荐)
        auth_pass 1111	#指定认证使用的密码,最多8位
    }
    virtual_ipaddress { #虚拟IP地址设置虚拟IP地址,供用户访问使用,可设置多个,一行一个
        192.168.200.222
    }
}

keepalived之vrrp_script

keepalived只能做到对网络故障和keepalived本身的监控,即当出现网络故障或者keepalived本身出现问题时,进行切换。但是这些还不够,我们还需要监控keepalived所在服务器上的其他业务,比如Nginx,如果Nginx出现异常了,仅仅keepalived保持正常,是无法完成系统的正常工作的,因此需要根据业务进程的运行状态决定是否需要进行主备切换,这个时候,我们可以通过编写脚本对业务进程进行检测监控。

实现步骤:

  1. 在keepalived配置文件中添加对应的配置像
vrrp_script 脚本名称
{
    script "脚本位置"
    interval 3 #执行时间间隔
    weight -20 #动态调整vrrp_instance的优先级
}
  1. 编写脚本

ck_nginx.sh

#!/bin/bash
num=`ps -C nginx --no-header | wc -l`
if [ $num -eq 0 ];then
 /usr/local/nginx/sbin/nginx
 sleep 2
 if [ `ps -C nginx --no-header | wc -l` -eq 0 ]; then
  killall keepalived
 fi
fi

Linux ps命令用于显示当前进程 (process) 的状态。

-C(command) :指定命令的所有进程

--no-header 排除标题

  1. 为脚本文件设置权限
chmod 755 ck_nginx.sh
  1. 将脚本添加到
sh
vrrp_script ck_nginx {
   script "/etc/keepalived/ck_nginx.sh" #执行脚本的位置
   interval 2		#执行脚本的周期,秒为单位
   weight -20		#权重的计算方式
}
vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 10
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.200.111
    }
    track_script {
      ck_nginx
    }
}
  1. 如果效果没有出来,可以使用 tail -f /var/log/messages查看日志信息,找对应的错误信息。